/*! Copyright(c) 2008-2012
 *
 *\file		Stm8s_spi.c
 *\brief		
 *\details	
 *
 *\author	Cai Peifeng
 *\version	
 *\date		10Jun12
 *
 *\warning	
 *
 *\history \arg	10Jun12, Cai Peifeng, Create the file
 */

#include "Stm8s_spi.h"

/*!
 *\fn			void SPI_DeInit();
 *\brief   
 *
 *\param[in]   
 *\param[out]  
 *
 *\return  
 *\retval  
 *
 *\note		  
 */
void SPI_DeInit()
{
	SPI->CR1 	= SPI_CR1_RESET_VALUE;
	SPI->CR2	= SPI_CR2_RESET_VALUE;
	SPI->ICR	= SPI_ICR_RESET_VALUE;
	SPI->SR		= SPI_SR_RESET_VALUE;
	SPI->CRCPR	= SPI_CRCPR_RESET_VALUE;
}


/*!
 *\fn			void SPI_Init();
 *\brief   
 *
 *\param[in]   
 *\param[out]  
 *
 *\return  
 *\retval  
 *
 *\note		  
 */
void SPI_Init(SPI_FirstBit_Typedef FirstBit, SPI_BaudRatePrescaler_TypeDef BaudRatePrescaler, 
			SPI_Mode_Typedef Mode, SPI_ClockPolarity_TypeDef ClockPolarity, SPI_ClockPhase_Typedef ClockPhase, 
			SPI_DataDirction_Typedef Data_Direction, SPI_NSS_TypeDef Slave_Management,uint8_t CRCPolynomial)
{
	assert_param(IS_SPI_FIRSTBIT_OK(FirstBit));
    assert_param(IS_SPI_BAUDRATE_PRESCALER_OK(BaudRatePrescaler));
    assert_param(IS_SPI_MODE_OK(Mode));
    assert_param(IS_SPI_POLARITY_OK(ClockPolarity));
    assert_param(IS_SPI_PHASE_OK(ClockPhase));
    assert_param(IS_SPI_DATA_DIRECTION_OK(Data_Direction));
    assert_param(IS_SPI_SLAVEMANAGEMENT_OK(Slave_Management));
    assert_param(IS_SPI_CRC_POLYNOMIAL_OK(CRCPolynomial));

	SPI->CR1 = (uint8_t)( (uint8_t)( (uint8_t)FirstBit | BaudRatePrescaler )| 
	(uint8_t)((uint8_t)ClockPolarity | ClockPhase));

	SPI->CR2 = (uint8_t)( (uint8_t)(Data_Direction) | (uint8_t)(Slave_Management));

	if( SPI_MODE_MASTER == Mode)
	{
		SPI->CR2 |= (uint8_t)SPI_CR2_SSI;
	}
	else
	{
		SPI->CR2 &= (uint8_t)(~SPI_CR2_SSI);
	}

	SPI->CR1 |= (uint8_t)(Mode);

	SPI->CRCPR = (uint8_t)CRCPolynomial;
}

/*!
 *\fn			void SPI_Cmd(FunctionalState NewState);
 *\brief   
 *
 *\param[in]   
 *\param[out]  
 *
 *\return  
 *\retval  
 *
 *\note		  
 */
void SPI_Cmd(FunctionalState NewState)
{
	assert_param(IS_FUNCTIONALSTATE_OK(NewState));

	if( DISABLE != NewState)
	{
		SPI->CR1 |= SPI_CR1_SPE;
	}
	else
	{
		SPI->CR1 &= (uint8_t)(~SPI_CR1_SPE);
	}
}

/*!
 *\fn			void SPI_ITConfig(SPI_IT_TypeDef SPI_IT, FunctionalState NewState);
 *\brief   
 *
 *\param[in]   
 *\param[out]  
 *
 *\return  
 *\retval  
 *
 *\note		  
 */
void SPI_ITConfig(SPI_IT_TypeDef SPI_IT, FunctionalState NewState)
{
	uint8_t itpos = 0;
	
	assert_param(IS_SPI_CONFIG_IT_OK(SPI_IT));
	assert_param(IS_FUNCTIONALSTATE_OK(NewState));

	itpos = (uint8_t)( (uint8_t)1 << (uint8_t)((uint8_t)SPI_IT & (uint8_t)0x0F));

	if( DISABLE != NewState)
	{
		SPI->ICR |= itpos;
	}
	else
	{
		SPI->ICR &= (uint8_t)(~itpos);
	}
}

/*!
 *\fn			void SPI_SendData(uint8_t Data);
 *\brief   
 *
 *\param[in]   
 *\param[out]  
 *
 *\return  
 *\retval  
 *
 *\note		  
 */
void SPI_SendData(uint8_t Data)
{
	SPI->DR = Data;
}

/*!
 *\fn			uint8_t SPI_ReceiveData(void);
 *\brief   
 *
 *\param[in]   
 *\param[out]  
 *
 *\return  
 *\retval  
 *
 *\note		  
 */
uint8_t SPI_ReceiveData(void)
{
	return (uint8_t)(SPI->DR);
}

/*!
 *\fn			void SPI_NSSInternalSoftwareCmd(FunctionalState NewState);
 *\brief   
 *
 *\param[in]   
 *\param[out]  
 *
 *\return  
 *\retval  
 *
 *\note		  
 */
void SPI_NSSInternalSoftwareCmd(FunctionalState NewState)
{
	assert_param(IS_FUNCTIONALSTATE_OK(NewState));

	if( DISABLE != NewState)
	{
		SPI->CR2 |= SPI_CR2_SSI;
	}
	else
	{
		SPI->CR2 &= (uint8_t)(~SPI_CR2_SSI);
	}
}

/*!
 *\fn			void SPI_TransmitCRC(void);
 *\brief   
 *
 *\param[in]   
 *\param[out]  
 *
 *\return  
 *\retval  
 *
 *\note		  
 */
void SPI_TransmitCRC(void)
{
	SPI->CR2 |= SPI_CR2_CRCNEXT;
}

/*!
 *\fn			void SPI_CalculateCRCCmd(FunctionalState NewState);
 *\brief   
 *
 *\param[in]   
 *\param[out]  
 *
 *\return  
 *\retval  
 *
 *\note		  
 */
void SPI_CalculateCRCCmd(FunctionalState NewState)
{
	assert_param(IS_FUNCTIONALSTATE_OK(NewState));

	if( DISABLE != NewState)
	{
		SPI->CR2 |= SPI_CR2_CRCEN;
	}
	else
	{
		SPI->CR2 &= (uint8_t)(~SPI_CR2_CRCEN);
	}
}

/*!
 *\fn			uint8_t SPI_GetCRC(SPI_CRC_TypeDef SPI_CRC);
 *\brief   
 *
 *\param[in]   
 *\param[out]  
 *
 *\return  
 *\retval  
 *
 *\note		  
 */
uint8_t SPI_GetCRC(SPI_CRC_TypeDef SPI_CRC)
{
	uint8_t crcreg = 0;
	
	assert_param(IS_SPI_CRC_OK(SPI_CRC));

	if( SPI_CRC_RX != SPI_CRC)
	{
		crcreg = SPI->TXCRCR;
	}
	else
	{
		crcreg = SPI->RXCRCR;
	}

	return crcreg;
}

/*!
 *\fn			void SPI_ResetCRC(void);
 *\brief   
 *
 *\param[in]   
 *\param[out]  
 *
 *\return  
 *\retval  
 *
 *\note		  
 */
void SPI_ResetCRC(void)
{
	SPI_CalculateCRCCmd(ENABLE);

	SPI_Cmd(ENABLE);
}

/*!
 *\fn			uint8_t SPI_GetCRCPolynomial(void);
 *\brief   
 *
 *\param[in]   
 *\param[out]  
 *
 *\return  
 *\retval  
 *
 *\note		  
 */
uint8_t SPI_GetCRCPolynomial(void)
{
	return SPI->CRCPR;
}

/*!
 *\fn			void SPI_BiDirectionalLineConfig(SPI_DataDirction_Typedef SPI_Direction);
 *\brief   
 *
 *\param[in]   
 *\param[out]  
 *
 *\return  
 *\retval  
 *
 *\note		  
 */
void SPI_BiDirectionalLineConfig(SPI_Direction_TypeDef SPI_Direction)
{
	assert_param(IS_SPI_DIRECTION_OK(SPI_Direction));

	if( SPI_DIRECTION_RX != SPI_Direction)
	{
		SPI->CR2 |= SPI_CR2_BDOE;
	}
	else
	{
		SPI->CR2 &= (uint8_t)(~SPI_CR2_BDOE);
	}
}

/*!
 *\fn			FlagStatus SPI_GetFlagStatus(SPI_Flag_TypeDef SPI_FLAG);
 *\brief   
 *
 *\param[in]   
 *\param[out]  
 *
 *\return  
 *\retval  
 *
 *\note		  
 */
FlagStatus SPI_GetFlagStatus(SPI_Flag_TypeDef SPI_FLAG)
{
	FlagStatus status = RESET;

	assert_param(IS_SPI_FLAGS_OK(SPI_FLAG));

	if( ( SPI->SR & (uint8_t)SPI_FLAG ) != (uint8_t)RESET)
	{
		status = SET;
	}
	else
	{
		status = RESET;
	}

	return status;
}

/*!
 *\fn			void SPI_ClearFlag(SPI_Flag_TypeDef SPI_FLAG);
 *\brief   
 *
 *\param[in]   
 *\param[out]  
 *
 *\return  
 *\retval  
 *
 *\note		  
 */
void SPI_ClearFlag(SPI_Flag_TypeDef SPI_FLAG)
{
	assert_param(IS_SPI_CLEAR_FLAGS_OK(SPI_FLAG));

	SPI->SR = (uint8_t)(~SPI_FLAG);
}

/*!
 *\fn			ITStatus SPI_GetITStatus(SPI_IT_TypeDef SPI_IT);
 *\brief   
 *
 *\param[in]   
 *\param[out]  
 *
 *\return  
 *\retval  
 *
 *\note		  
 */
ITStatus SPI_GetITStatus(SPI_IT_TypeDef SPI_IT)
{
	ITStatus pendingbitstatus = RESET;

	uint8_t itpos = 0;
	uint8_t itmask1 = 0;
	uint8_t itmask2 = 0;
	uint8_t enablestatus = 0;

	assert_param(IS_SPI_GET_IT_OK(SPI_IT));

	itpos = (uint8_t)((uint8_t)1 << ((uint8_t)SPI_IT & (uint8_t)0x0F));

	itmask1 = (uint8_t)((uint8_t)SPI_IT >> (uint8_t)4);
	itmask2 = (uint8_t)((uint8_t) 1 << itmask1);

	enablestatus = (uint8_t)((uint8_t)SPI->SR & itmask2);

	if( ( (SPI->ICR & itpos) != RESET ) && enablestatus)
	{
		pendingbitstatus = SET;
	}
	else
	{
		pendingbitstatus = RESET;
	}

	return pendingbitstatus;
	
}

/*!
 *\fn			void SPI_ClearITPendingBit(SPI_IT_TypeDef SPI_IT);
 *\brief   
 *
 *\param[in]   
 *\param[out]  
 *
 *\return  
 *\retval  
 *
 *\note		  
 */
void SPI_ClearITPendingBit(SPI_IT_TypeDef SPI_IT)
{
	uint8_t itpos = 0;

	assert_param(IS_SPI_CLEAR_IT_OK(SPI_IT));

	itpos = (uint8_t)((uint8_t)1 << (uint8_t)((uint8_t)(SPI_IT & (uint8_t)0xF0) >> 4));

	SPI->SR = (uint8_t)(~itpos);
	
}



